package com.xl.activiti.demo.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhongwm
 */
@Slf4j
@RestController
@RequestMapping("/task")
public class TaskController {

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;

    @Resource
    private HistoryService historyService;

    /**
     * 启动新实例
     *
     * @param instanceKey
     * @return
     */
    @GetMapping("/start/{instanceKey}")
    public String testStartProcess(@PathVariable("instanceKey") String instanceKey, HttpServletRequest request) {
        log.info("request params:{}", JSONUtil.toJsonStr(request.getParameterMap()));
        Map<String, Object> params = new HashMap<>();
        params.put("userId", IdUtil.simpleUUID());
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(instanceKey, params);
        log.info("instanceId:{}", processInstance.getId());
        log.info("instance:{}", processInstance);
        return processInstance.getId();
    }

    /**
     * 启动新实例
     *
     * @param params
     * @return
     */
    @PostMapping("/start")
    public String postStartProcess(@RequestBody JSONObject params) {
        log.info("request params:{}", params);
        String instanceKey = "instanceKey";
        String businessKey = "businessKey";
        String instanceValue = null;
        String businessValue = null;
        if (params != null && params.containsKey(instanceKey)) {
            instanceValue = params.getStr(instanceKey);
            params.remove(instanceKey);
        }
        if (params != null && params.containsKey(businessKey)) {
            businessValue = params.getStr(businessKey);
            params.remove(businessKey);
        }

        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(instanceValue).singleResult();
        if (definition != null) {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(definition.getId());
            //.getFlowElement(definition.)
            log.info("bpmnModel:{}", bpmnModel);
        }

        if (params != null && params.containsKey("userId")) {
            Authentication.setAuthenticatedUserId(params.getStr("userId"));
            params.remove("userId");
        }

        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(instanceValue, businessValue, params);
        log.info("instanceId:{}", processInstance.getId());
        log.info("instance:{}", processInstance);
        return processInstance.getId();
    }

    /**
     * 查询用户待处理任务
     *
     * @param username
     * @return
     */
    @GetMapping("/query/{username}")
    public String queryTasks(@PathVariable("username") String username) {
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(username).list();
        return JSONUtil.toJsonStr(taskList);
    }

    /**
     * 处理任务
     *
     * @param json
     * @return
     */
    @PostMapping("/complete")
    public String completeTask(@RequestBody JSONObject json) {
        String username = json.getStr("username");
        //任务id
        String taskId = json.getStr("taskId");
        if (StrUtil.isBlank(taskId)) {
            return "taskId invalid.";
        }
        log.info("username:{}, taskId:{}", username, taskId);
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return "task not found.";
        }

        log.info("task:{}", task);
        /**
        log.info("task FormKey:{}", task.getFormKey());
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        log.info("bpmnModel:{}", bpmnModel.toString());
        if (bpmnModel != null) {
            UserTask userTask = (UserTask) bpmnModel.getFlowElement(task.getTaskDefinitionKey());
            log.info("element:{}", userTask);
            if (userTask != null) {
                userTask.getFormProperties().forEach(p ->
                        log.info("formProperties:{}, {}, {}, {}",
                                p.isRequired(),
                                p.getId(), p.getType(), p.getName(), p.getFormValues()));
            }
        }
         **/

        UserTask userTask = (UserTask) repositoryService.getBpmnModel(task.getProcessDefinitionId())
                .getFlowElement(task.getTaskDefinitionKey());
        log.info("userTask:{}", userTask);
        if (userTask != null) {
            log.info("formProperties:{}", userTask.getFormProperties());
            userTask.getFormProperties().forEach(p ->
                    log.info("formProperties:id:{}, type:{}, name:{}, required:{}, expression:{}",
                            p.getId(), p.getType(), p.getName(), p.isRequired(), p.getExpression()));
        }

        if (task != null) {
            JSONObject params = json.getJSONObject("params");
            log.info("params:{}", params);
            if (params != null) {
                Map<String, Object> map = new HashMap<>();
                map.put("url", params.getStr("url"));
                //map.put("params", params.getJSONObject("params"));
                //设置全部参数
                taskService.complete(taskId, params);
                //taskService.complete(taskId);
            } else {
                taskService.complete(taskId);
            }
            return "task completed.";
        }
        return "task not found.";
    }

    @GetMapping("/query")
    public void queryTaskList() {
        List<Task> list = taskService.createTaskQuery().taskAssignee("jack").list();
        for (Task task : list) {
            log.info("find task:{}, definitionKey:{}, formKey:{}", task, task.getTaskDefinitionKey(), task.getFormKey());
            if ("usertask2".equals(task.getTaskDefinitionKey())) {
                taskService.complete(task.getId());
                log.info("complete task:{}", task);
            }
        }
    }

    @GetMapping("/complete")
    public void queryTaskAndComplete() {
        Task task = taskService.createTaskQuery().taskAssignee("jack").singleResult();
        log.info("find task:{}", task);
        if (task != null) {
            JSONObject json = new JSONObject();
            json.set("username", "张三");
            json.set("age", 20);
            Map<String, Object> params = new HashMap<>();
            params.put("url", "http://localhost:8080/hello");
            params.put("params", json);
            taskService.complete(task.getId(), params);
            log.info("complete task:{}", task);
        } else {
            log.info("not task found.");
        }
    }

}
